package chatroomserver;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

import chatroomclient.Friend;
import chatroomsend.Send;
import chatroomutil.ChatRoomUtil;
import chatroomutil.Server;
import java.sql.*;
import java.util.List;

import chatroomutil.DBUtil;

public class ServerServer extends Server {
    Hashtable<String, User> onlineTable = new Hashtable<String, User>();// 在线用户集合
    Hashtable<String, User> offlineTable = new Hashtable<String, User>();// 离线用户集合
    // 用户内部类
     class User {
         String id;
         String pwd;
         String IP;
         int port;
         User(String id, String pwd) {
            this.id = id;
             this.pwd = pwd;
         }
     }
     // 发送进程内部类
     class sendThread implements Runnable {
         String mesg;
         String IP;
         int port;
         sendThread(String IP, int port, String mesg) {
             this.IP = IP;
             this.port = port;
             this.mesg = mesg;
         }
         @Override
         public void run() {
             Send sendClient = new Send();
             sendClient.connect(IP, port, 1000);
             sendClient.send(mesg);
         }
     };
     public ServerServer(int port) throws IOException {
         init(port);
         initUsers();
         listen();
     }
    private int init(int port) throws IOException {
         try {
             sSocket = new ServerSocket(port);//绑定指定端口
         } catch (IOException e) {
             ChatRoomUtil.showErrorBox("服务器初始化失败，无法绑定端口。");
             System.exit(-1);
        }
        return port;
    }
    private int initUsers() {
        String sql = "SELECT username, password FROM user";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {

            while (rs.next()) {
                String id = rs.getString("username");
                String pwd = rs.getString("password");
                User user = new User(id, pwd);
                offlineTable.put(id, user); // 初始状态为离线
            }
        } catch (Exception e) {
            ChatRoomUtil.showErrorBox("数据库查询用户失败");
            System.exit(-1);
        }
        return 0;
    }

    /**
     * 获取所有用户列表
     */
    private List<String> getAllUsers() {
        List<String> allUsers = new ArrayList<>();
        String sql = "SELECT username FROM user";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {

            while (rs.next()) {
                allUsers.add(rs.getString("username"));
            }
        } catch (SQLException e) {
            ChatRoomUtil.showErrorBox("获取所有用户列表失败: " + e.getMessage());
        }
        return allUsers;
    }

    /**
     * 处理添加好友请求
     */
    private int addFriendRequest(String userId, String friendId) {
        String sql = "INSERT INTO friend(userid, friendid, status) VALUES (?, ?, 0)";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, userId);
            pstmt.setString(2, friendId);
            pstmt.executeUpdate();
            return 0;
        } catch (SQLException e) {
            ChatRoomUtil.showErrorBox("添加好友请求失败: " + e.getMessage());
            return -1;
        }
    }

    private int acceptFriendRequest(String userId, String friendId) {
        Connection conn = null;
        try {
            conn = DBUtil.getConnection();
            conn.setAutoCommit(false); // 开启事务

            // 1. 正向更新：将原请求状态设为 1（userId -> friendId）
            String updateSql = "UPDATE friend SET status = 1 WHERE userid = ? AND friendid = ?";
            try (PreparedStatement updateStmt = conn.prepareStatement(updateSql)) {
                updateStmt.setString(1, userId);
                updateStmt.setString(2, friendId);
                updateStmt.executeUpdate();
            }

            // 2. 反向插入：添加新的记录（friendId -> userId）
            String insertSql = "INSERT INTO friend(userid, friendid, status) VALUES (?, ?, 1)";
            try (PreparedStatement insertStmt = conn.prepareStatement(insertSql)) {
                insertStmt.setString(1, friendId);
                insertStmt.setString(2, userId);
                insertStmt.executeUpdate();
            }

            conn.commit(); // 提交事务
            return 0;

        } catch (SQLException e) {
            try {
                if (conn != null) conn.rollback(); // 出错回滚
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            ChatRoomUtil.showErrorBox("接受好友请求失败: " + e.getMessage());
            return -1;
        } finally {
            try {
                if (conn != null) conn.setAutoCommit(true);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    private java.util.List<Friend> getFriendsList(String userId) {
        List<Friend> friends = new ArrayList<>();
        String sql = "SELECT friendid, friendname, status FROM friend WHERE userid = ? AND status = 1";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, userId);
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                friends.add(new Friend(userId, rs.getString("friendid"),
                        rs.getString("friendname"), rs.getInt("status")));
            }
        } catch (SQLException e) {
            ChatRoomUtil.showErrorBox("获取好友列表失败: " + e.getMessage());
        }
        return friends;
    }



    /**
     *
     * @param id
     * @param pwd
     * @param phone
     * @param firstName
     * @param lastName
     * @param age
     * @param sex
     * @return
     */
    private int saveNewUser(String id, String pwd, String phone, String firstName, String lastName, int age, String sex) {
        String sql = "INSERT INTO user(username, password, phone, first_name, last_name, age, sex) VALUES (?, ?, ?, ?, ?, ?, ?)";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {

            pstmt.setString(1, id);
            pstmt.setString(2, pwd); // 建议加密存储
            pstmt.setString(3, phone);
            pstmt.setString(4, firstName);
            pstmt.setString(5, lastName);
            pstmt.setInt(6, age);
            pstmt.setString(7, sex);

            pstmt.executeUpdate();
        } catch (Exception e) {
            ChatRoomUtil.showErrorBox("写入用户到数据库失败: " + e.getMessage());
            System.exit(-1);
        }
        return 0;
    }


    String loginCheck(String id, String pwd, String IP, int port) {//检查登录用户的合法性
         System.out.println("logi check");
         if (onlineTable.containsKey(id))
             return "alreadyonline";//该用户已在线
         User f = offlineTable.get(id);
         if (f == null)
             return "nothisid";//无此用户
         if (f.pwd.compareTo(pwd) == 0) {
             oneUserOnline(id, IP, port);
             sendOnlinesToNewOnlineUser(id, IP, port);
             sendNewOnlineUserToOnlines(id);
             return "yes";//合法
         } else {
             return "wrong";//密码错误
         }
     }
     int oneUserOnline(String id, String IP, int port) {//一个新用户上线
         User f = offlineTable.get(id);
         offlineTable.remove(id);
         onlineTable.put(id, f);
         f.IP = IP;
         f.port = port;
         return 0;
     }
     int sendNewOnlineUserToOnlines(String id) {//给所有在线用户发送新上线的用户的id
         Enumeration<User> fs = onlineTable.elements();
         while (fs.hasMoreElements()) {
             User f = fs.nextElement();
             if (f.id.compareTo(id) != 0) {
                 Thread hThread = new Thread(
                         new sendThread(f.IP, f.port, "newf" + id));
                 hThread.start();
             }
         }
         return 0;
     }
     int sendMesg(String mesg) {//向所有在线用户转发一条消息
         Enumeration<User> fs = onlineTable.elements();
         while (fs.hasMoreElements()) {
             User f = fs.nextElement();
             Thread hThread = new Thread(
                     new sendThread(f.IP, f.port, "mesg" + mesg));
             hThread.start();
         }
         return 0;
     }
     int sendChat(String id, String mesg) {//向一个用户发送一条一对一聊天的消息
         User f = onlineTable.get(id);
         Thread hThread = new Thread(
                 new sendThread(f.IP, f.port, "chat" + mesg));
         hThread.start();
         return 0;
     }
    String newRegisUser(String id, String pwd, String phone, String firstName, String lastName, int age, String sex) {
        if (onlineTable.containsKey(id) || offlineTable.containsKey(id)) {
            return "no";
        }
        User user = new User(id, pwd);
        offlineTable.put(id, user);
        saveNewUser(id, pwd, phone, firstName, lastName, age, sex);
        return "yes";
    }
     int sendOnlinesToNewOnlineUser(String id, String IP, int port) {//给新上线的用户发送所有已在线用户的id
         if (onlineTable.isEmpty() || onlineTable.size() == 1) {
             return 0;
         }
         StringBuffer strBuf = new StringBuffer();
         Enumeration<User> fs = onlineTable.elements();
         while (fs.hasMoreElements()) {
             User f = fs.nextElement();
             if (f.id.compareTo(id) != 0) {
                 strBuf.append(f.id);
                 strBuf.append(";");
             }
         }
         String str = strBuf.toString();
         Thread hThread = new Thread(new sendThread(IP, port, "newf" + str));
         hThread.start();
         return 0;
     }
     int oneUserOffline(String id) {//有一个用户下线，将其下线消息发送给所有在线用户
         Enumeration<User> fs = onlineTable.elements();
         while (fs.hasMoreElements()) {
             User f = fs.nextElement();
             if (f.id.compareTo(id) == 0) {
                 onlineTable.remove(id);
                 offlineTable.put(id, f);
             } else {
                 Thread hThread = new Thread(
                         new sendThread(f.IP, f.port, "offl" + id));
                 hThread.start();
             }
         }
         return 0;
     }
     @Override
     protected  String handle(Socket ots,String rMessage){
         System.out.println("handle");
         if (rMessage.startsWith("regi")) {
             rMessage = rMessage.substring("regi".length());
             String[] parts = rMessage.split(",", 8); // 分割更多字段
             String id = parts[0];
             String pwd = parts[1];
             String phone = parts[2];
             String firstName = parts[3];
             String lastName = parts[4];
             int age = Integer.parseInt(parts[5]);
             String sex = parts[6];

             return newRegisUser(id, pwd, phone, firstName, lastName, age, sex);
         }
         if (rMessage.startsWith("logi")) {//登录
             System.out.println("logi");
             rMessage = rMessage.substring("logi".length());
             String id = rMessage.substring(0, rMessage.indexOf(','));
             String pwd = rMessage.substring(rMessage.indexOf(',') + 1,
                     rMessage.lastIndexOf(','));
             String portstr = rMessage.substring(rMessage.lastIndexOf(',') + 1);
             int port = new Integer(portstr);
             String IP = ots.getInetAddress().getHostAddress();
             return loginCheck(id, pwd, IP, port);
         }
         if (rMessage.startsWith("mesg")) {//聊天室消息
             String mesg = rMessage.substring(("mesg").length());
             sendMesg(mesg);
             return "getm";
         }
         if (rMessage.startsWith("chat")) {//一对一消息
             String chat = rMessage.substring(("chat").length());
             String id = chat.substring(0, chat.indexOf(':'));
             String mesg = chat.substring(chat.indexOf(':') + 1);
             sendChat(id, mesg);
             return "getm";
         }
         if (rMessage.startsWith("offl")) {//下线
             String id = rMessage.substring(("offl").length());
             oneUserOffline(id);
             return "getm";
         }
         if (rMessage.startsWith("allu")) { // 获取所有用户列表
            List<String> allUsers = getAllUsers();
            StringBuilder sb = new StringBuilder();
            for (String user : allUsers) {
                sb.append(user).append(";");
            }
            return sb.toString();
        }

        if (rMessage.startsWith("addf")) { // 添加好友请求
            rMessage = rMessage.substring("addf".length());
            String[] parts = rMessage.split(":", 2);
            String userId = parts[0];
            String friendId = parts[1];
            addFriendRequest(userId, friendId);
            return "added";
        }
         if (rMessage.startsWith("accf")) { //接受好友请求
             rMessage = rMessage.substring("accf".length());
             String[] parts = rMessage.split(":", 2);
             String userId = parts[0];
             String friendId = parts[1];
             acceptFriendRequest(userId, friendId);
             return "accepted";
         }
         if (rMessage.startsWith("listf")) { //获取好友列表
             String userId = rMessage.substring("listf".length());
             List<Friend> friends = getFriendsList(userId);
             StringBuilder sb = new StringBuilder();
             for (Friend f : friends) {
                 sb.append(f.getFriendId()).append(":").append(f.getFriendName()).append(";");
             }
             return sb.toString();
         }
         if (rMessage.startsWith("pendingf")) { // 获取待处理的好友请求
             String userId = rMessage.substring("pendingf".length());
             List<String> pendingList = getPendingFriendRequests(userId);
             StringBuilder sb = new StringBuilder();
             for (String fid : pendingList) {
                 sb.append(fid).append(";");
             }
             return sb.toString();
         }
         if (rMessage.startsWith("searchu")) {
             String keyword = rMessage.substring("searchu".length());
             List<String> matchedUsers = searchUsers(keyword);
             StringBuilder sb = new StringBuilder();
             for (String user : matchedUsers) {
                 sb.append(user).append(";");
             }
             return sb.toString();
         }
         if (rMessage.startsWith("delf")) {
             rMessage = rMessage.substring("delf".length());
             String[] parts = rMessage.split(":", 2);
             String userId = parts[0];
             String friendId = parts[1];
             deleteFriend(userId, friendId);
             return "deleted";
         }

         if (rMessage.startsWith("renamef")) {
             rMessage = rMessage.substring("renamef".length());
             String[] parts = rMessage.split(":", 3);
             String userId = parts[0];
             String friendId = parts[1];
             String newName = parts[2];
             updateFriendName(userId, friendId, newName);
             return "renamed";
         }
         return "getm";
     }

    private int deleteFriend(String userId, String friendId) {
        String sql = "DELETE FROM friend WHERE userid = ? AND friendid = ?";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, userId);
            pstmt.setString(2, friendId);
            pstmt.executeUpdate();
            pstmt.setString(1, friendId);
            pstmt.setString(2, userId);
            pstmt.executeUpdate();
            return 0;
        } catch (SQLException e) {
            ChatRoomUtil.showErrorBox("删除好友失败: " + e.getMessage());
            return -1;
        }
    }

    private int updateFriendName(String userId, String friendId, String newName) {
        String sql = "UPDATE friend SET friendname = ? WHERE userid = ? AND friendid = ?";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, newName);
            pstmt.setString(2, userId);
            pstmt.setString(3, friendId);
            pstmt.executeUpdate();
            return 0;
        } catch (SQLException e) {
            ChatRoomUtil.showErrorBox("修改备注失败: " + e.getMessage());
            return -1;
        }
    }

    private List<String> searchUsers(String keyword) {
        List<String> results = new ArrayList<>();
        String sql = "SELECT username FROM user WHERE username LIKE ?";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, "%" + keyword + "%");
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                results.add(rs.getString("username"));
            }
        } catch (SQLException e) {
            ChatRoomUtil.showErrorBox("搜索用户失败: " + e.getMessage());
        }
        return results;
    }

    private List<String> getPendingFriendRequests(String userId) {
        List<String> pendingRequests = new ArrayList<>();
        String sql = "SELECT friendid FROM friend WHERE userid = ? AND status = 0";

        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {

            pstmt.setString(1, userId);
            ResultSet rs = pstmt.executeQuery();

            while (rs.next()) {
                pendingRequests.add(rs.getString("friendid"));
            }
        } catch (SQLException e) {
            ChatRoomUtil.showErrorBox("获取待处理好友请求失败: " + e.getMessage());
        }

        return pendingRequests;
    }


    public static void main(String[] args) {
         try {
             new ServerServer(65142);
         } catch (IOException e) {
             e.printStackTrace();
         }
     }
 }